home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / netbon.zip / SPX2WAY.PAS < prev    next >
Pascal/Delphi Source File  |  1992-11-14  |  9KB  |  300 lines

  1. (***********************************************************************
  2.   SPX2WAY.PAS - demonstrates how to set up a two-way SPX communication
  3.                 channel. Also demonstrates how to use an IPX broadcast
  4.                 to find a cooperating partner for an SPX message
  5.                 session.
  6.  
  7.                 Start the "host" by running SPX2WAY on one workstation
  8.                 with no command line parameters. Then start the
  9.                 "station" by running SPX2WAY on another workstation
  10.                 with at least one command line parameter.
  11.  
  12.                 Press <Esc> to break the connection. Press any other
  13.                 key to be prompted for a string to send to the other
  14.                 station.
  15.  
  16.                 Requires SPX version 3.00 or later. Use Novell's
  17.                 NVER utility to check your SPX driver version.
  18.  
  19.                 Kim Kokkonen, TurboPower Software
  20.                 Version 1.0 - 11/12/92
  21.                 Based on a test program provided by Richard DeMello
  22.                 and Steve Pasikowski at Core Technology Corp.
  23. ************************************************************************)
  24.  
  25. {$IFDEF Windows}
  26.   {$DEFINE WinOrDPMI}
  27. {$ENDIF}
  28. {$IFDEF DPMI}
  29.   {$DEFINE WinOrDPMI}
  30. {$ENDIF}
  31.  
  32. {$R-,S-,I-}
  33. program Spx2Way;
  34.  
  35. uses
  36.   {$IFDEF Windows}
  37.   WinCrt,
  38.   {$ELSE}
  39.   Crt,
  40.   {$ENDIF}
  41.   {$IFDEF WinOrDPMI}
  42.   WinDPMI,
  43.   {$ENDIF}
  44.   Netware;
  45.  
  46. const
  47.   Socket1 = $4445;              {Sockets used for each direction of connection}
  48.   Socket2 = $4446;
  49.   NumSPXECBs = 4;               {Number of listening ECBs}
  50.   ConnectionMade : Boolean = False; {True if session created}
  51.  
  52. const
  53.   MessageType = 0;              {Type code for each SPX message sent}
  54. type
  55.   Message = String;             {Type of user data for each SPX message}
  56.  
  57. var
  58.   {$IFDEF WinOrDPMI}
  59.   IPXEvent : WinIPXRec;         {Global IPX event variable}
  60.   SPXEvent : WinSPXRec;         {Global SPX event variable}
  61.   SendESR  : WinESRType;        {Do-nothing SPX event service routine}
  62.   MessagePR: ^Message;          {Message pointer, real mode}
  63.   MessagePP: ^Message;          {Message pointer, protected mode}
  64.   {$ELSE}
  65.   IPXEvent : IPXRec;            {Global IPX event variable}
  66.   SPXEvent : SPXRec;            {Global SPX event variable}
  67.   SendESR  : Pointer;           {Do-nothing SPX event service routine}
  68.   MessagePR: ^Message;          {Message pointer}
  69.   {$ENDIF}
  70.   SaveExit : Pointer;           {Saved exit procedure}
  71.  
  72. procedure CheckNetWare;
  73. var
  74.   LoggedOn : Boolean;
  75.   Version : Word;
  76.   MaxSPXConn : Word;
  77.   AvailSPXConn : Word;
  78. begin
  79.   if not NetWareLoaded(LoggedOn) then begin
  80.     WriteLn('NetWare drivers must be loaded');
  81.     Halt;
  82.   end;
  83.   if not SPXServicesAvail(Version, MaxSPXConn, AvailSPXConn) then begin
  84.     WriteLn('SPX services are not available');
  85.     Halt;
  86.   end;
  87.   if Version < $0300 then begin
  88.     WriteLn('SPX version must be at least 3.00');
  89.     Halt;
  90.   end;
  91. end;
  92.  
  93. {$F+}
  94. procedure FreeResources;
  95. begin
  96.   ExitProc := SaveExit;
  97.   if ConnectionMade then begin
  98.     SPXTerminateConn(SPXEvent);
  99.     ConnectionMade := False;
  100.     WriteLn('Connection terminated');
  101.   end;
  102.   {$IFDEF WinOrDPMI}
  103.   if SPXEvent.wsrP <> nil then
  104.     FreeWinSPXRec(SPXEvent);
  105.   if IPXEvent.wirP <> nil then
  106.     FreeWinIPXRec(IPXEvent);
  107.   if MessagePP <> nil then
  108.     FreeRealModeMem(MessagePP);
  109.   if SendESR.PoolPtr <> nil then
  110.     FreeWindowsESR(SendESR);
  111.   {$ELSE}
  112.   FreeMem(MessagePR, SizeOf(Message));
  113.   {$ENDIF}
  114. end;
  115. {$F-}
  116.  
  117. procedure AllocateResources;
  118. begin
  119.   {Install exit procedure to clean up}
  120.   SaveExit := ExitProc;
  121.   ExitProc := @FreeResources;
  122.  
  123.   {$IFDEF WinOrDPMI}
  124.   FillChar(SPXEvent, SizeOf(SPXEvent), 0);
  125.   FillChar(IPXEvent, SizeOf(IPXEvent), 0);
  126.   FillChar(SendESR, SizeOf(SendESR), 0);
  127.   MessagePP := nil;
  128.   {No user data is transferred via IPX, so use a 1 byte data buffer}
  129.   if not AllocateWinIPXRec(1, IPXEvent) then begin
  130.     WriteLn('Unable to allocate IPXEvent');
  131.     Halt;
  132.   end;
  133.   if not AllocateWinSPXRec(SPXEvent) then begin
  134.     WriteLn('Unable to allocate SPXEvent');
  135.     Halt;
  136.   end;
  137.   {Variables of type Message are transferred via SPX}
  138.   if not GetRealModeMem(SizeOf(Message),
  139.                         Pointer(MessagePR), Pointer(MessagePP)) then begin
  140.     Writeln('Unable to allocate message buffer');
  141.     Halt;
  142.   end;
  143.   if not AllocateWindowsESR(NoESR, DSeg, SendESR) then begin
  144.     WriteLn('Unable to allocate windows ESR');
  145.     Halt;
  146.   end;
  147.   {$ELSE}
  148.   MessagePR := nil;
  149.   if MaxAvail < SizeOf(Message) then begin
  150.     Writeln('Unable to allocate message buffer');
  151.     Halt;
  152.   end;
  153.   GetMem(MessagePR, SizeOf(Message));
  154.   SendESR := nil;
  155.   {$ENDIF}
  156. end;
  157.  
  158. procedure HaltIfKeyPressed;
  159. begin
  160.   if KeyPressed then begin
  161.     WriteLn('Aborted by user');
  162.     Halt;
  163.   end;
  164. end;
  165.  
  166. procedure HaltIfError(Status : Byte);
  167. begin
  168.   if Status <> 0 then begin
  169.     WriteLn('Error: ', Status);
  170.     Halt;
  171.   end;
  172. end;
  173.  
  174. procedure InitHost;
  175. var
  176.   StationAddr : IPXAddress;
  177.   Status : Byte;
  178.   IPXBuf : Byte;
  179. begin
  180.   WriteLn('Host Mode.');
  181.  
  182.   Write('Waiting for IPX broadcast on socket ', Socket1, '... ');
  183.   Status := IPXListen(IPXEvent, Socket1, False, 1, IPXBuf);
  184.   if Status = 0 then
  185.     while not IPXEventComplete(IPXEvent, Status) do
  186.       HaltIfKeyPressed;
  187.   HaltIfError(Status);
  188.  
  189.   {The address of the station is now in the IPXEvent}
  190.   {$IFDEF WinOrDPMI}
  191.   StationAddr := IPXEvent.wirP^.IPXHead.Source;
  192.   {$ELSE}
  193.   StationAddr := IPXEvent.IPXHead.Source;
  194.   {$ENDIF}
  195.   {Use a second socket for reverse connection}
  196.   StationAddr.Socket := Swap(Socket2);
  197.  
  198.   WriteLn;
  199.   Write('IPX broadcast received. Establishing SPX connection... ');
  200.   Status := SPXEstablishConn(SPXEvent, StationAddr, Socket1, True,
  201.                              SizeOf(Message), NumSPXECBs, SendESR);
  202.   HaltIfError(Status);
  203.   ConnectionMade := True;
  204.   WriteLn;
  205. end;
  206.  
  207. procedure InitStation;
  208. var
  209.   HostAddr : IPXAddress;
  210.   Status : Byte;
  211.   ComplCode : Byte;
  212.   DataType : Byte;
  213.   IPXBuf : Byte;
  214. begin
  215.   WriteLn('Station Mode.');
  216.  
  217.   WriteLn('Broadcasting IPX on socket ',
  218.           Socket1,
  219.           ' and waiting for SPX connection... ');
  220.   Status := SPXListenForConn(SPXEvent, Socket2, False, SizeOf(Message),
  221.                              NumSPXECBs, SendESR);
  222.   while not SPXEventComplete(SPXEvent, ComplCode, DataType) do begin
  223.     {Send an IPX broadcast}
  224.     {$IFDEF WinOrDPMI}
  225.     IPXEvent.wirP^.IPXHead.PacketType := $FE;
  226.     {$ELSE}
  227.     IPXEvent.IPXHead.PacketType := $FE;
  228.     {$ENDIF}
  229.     FillChar(HostAddr.Node, 6, $FF);
  230.     HostAddr.Network := 0;
  231.     HostAddr.Socket := Socket1;
  232.     Status := IPXSend(IPXEvent, HostAddr, Socket1, True, 1, IPXBuf);
  233.     HaltIfKeyPressed;
  234.   end;
  235.  
  236.   WriteLn;
  237.   WriteLn('SPX connection established');
  238.   ConnectionMade := True;
  239.  
  240.   {Store the connection ID}
  241.   {$IFDEF WinOrDPMI}
  242.   SPXEvent.wsrP^.ConnID := Word(SPXEvent.wsrP^.ECB.ECBP^.IPXWorkspace);
  243.   {$ELSE}
  244.   SPXEvent.ConnID := Word(SPXEvent.ECB.IPXWorkspace);
  245.   {$ENDIF}
  246. end;
  247.  
  248. procedure TransmitAndReceive;
  249. var
  250.   Key : Char;
  251.   ComplCode : Byte;
  252.   PoolIndex : Byte;
  253.   DataType : Byte;
  254.   MessagePtr : ^Message;
  255. begin
  256.   WriteLn;
  257.   WriteLn('Ready to transmit messages. <Esc> to quit, any other key to send.');
  258.   repeat
  259.     if KeyPressed then begin
  260.       {Keyboard command}
  261.       Key := ReadKey;
  262.       if Key = #27 {ESC} then
  263.         Exit;
  264.       {Send a message}
  265.       Write('Enter message: ');
  266.       {$IFDEF WinOrDPMI}
  267.       ReadLn(MessagePP^);
  268.       SPXSend(SPXEvent, True, MessageType, Length(MessagePP^)+1, MessagePR);
  269.       {$ELSE}
  270.       ReadLn(MessagePR^);
  271.       SPXSend(SPXEvent, True, MessageType, Length(MessagePR^)+1, MessagePR^);
  272.       {$ENDIF}
  273.       WriteLn('<Sent>');
  274.     end;
  275.     if SPXListenPooled(SPXEvent, ComplCode, PoolIndex,
  276.                        DataType, Pointer(MessagePtr)) then
  277.       if (ComplCode = 0) and (DataType = MessageType) then begin
  278.         {Message received}
  279.         WriteLn('Message received: "', MessagePtr^, '"');
  280.         SPXReplenishPool(SPXEvent, PoolIndex);
  281.       end else begin
  282.         {Connection terminated or other error}
  283.         (*WriteLn('Completion code ', ComplCode, '  DataType ', DataType);*)
  284.         Exit;
  285.       end;
  286.   until False;
  287. end;
  288.  
  289. begin
  290.   CheckNetWare;
  291.   AllocateResources;
  292.   if ParamCount = 0 then
  293.     {Host side, wait for call from station}
  294.     InitHost
  295.   else
  296.     {Station side, look for host}
  297.     InitStation;
  298.   TransmitAndReceive;
  299. end.
  300.